package com.xxx.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.MessageFormat;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.xxx.constant.RedisConstants;
import com.xxx.controller.BaseController;
import com.xxx.dto.BaseDTO;
import com.xxx.dto.ResponseDTO;
import com.xxx.util.JedisUtil;
import com.xxx.util.JsonUtil;

/**
 * 系统拦截器
 * 
 * 
 * 
 */
public class SystemInterceptor extends HandlerInterceptorAdapter {
	
	private static final Logger logger = LoggerFactory.getLogger(SystemInterceptor.class);

	//在执行handler之前来执行的
    //用于用户认证校验、用户权限校验
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		logger.debug("enter preHandle()...");
		request.setAttribute("begin_nano_time", System.nanoTime());
		
		// 校验token
		String token = request.getHeader("token");
		String uri = request.getRequestURI();
		if(StringUtils.isEmpty(token)) { // token为空
			logger.error("Uri {} token is null.", uri);
			ResponseDTO responseDTO = ResponseDTO.builtFail(BaseDTO.NOT_LOGON, "token is empty.");
			responseOutWithJson(response, JsonUtil.encodeJson(responseDTO));
			return false;
		}
		
		// 通过token从redis中获取userId
		String redisKey = MessageFormat.format(RedisConstants.REDIS_KEY_TOKEN, token);
		String userId = JedisUtil.get(redisKey);
		if(StringUtils.isEmpty(userId)) {
			logger.error("Uri {} token is invalid or exipred.", uri);
			ResponseDTO responseDTO = ResponseDTO.builtFail(BaseDTO.NOT_LOGON, "token is invalid or exipred.");
			responseOutWithJson(response, JsonUtil.encodeJson(responseDTO));
			return false;
		}
		
		// 将获取到的userId放到request中
		request.setAttribute(BaseController.USER_ID, userId);
		
		return true;
	}

	//在执行handler返回modelAndView之前来执行
    //如果需要向页面提供一些公用 的数据或配置一些视图信息，使用此方法实现 从modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    	logger.debug("enter postHandle()...");
    	long begin_nano_time = (Long) request.getAttribute("begin_nano_time");
    	long interval = System.nanoTime() - begin_nano_time;
    	logger.info("uri {} spent time(ms): {}", request.getRequestURI(), interval/1000000);
    }
    
    //执行handler之后执行此方法
    //作系统 统一异常处理，进行方法执行性能监控，在preHandle中设置一个时间点，在afterCompletion设置一个时间，两个时间点的差就是执行时长
    //实现 系统 统一日志记录
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    	logger.debug("enter afterCompletion()...");
    	if(ex!=null) {
    		logger.error("uri {} happend exception: {}", request.getRequestURI(), ex);
    	}
    }
    
    /** 
     * response 输出 json
     */  
    private void responseOutWithJson(HttpServletResponse response, String json) {  
        response.setCharacterEncoding("UTF-8");  
        response.setContentType("application/json; charset=utf-8");  
        PrintWriter out = null;  
        try {  
            out = response.getWriter();  
            out.append(json);  
        } catch (IOException e) {  
            logger.error("responseOutWithJson exception", e); 
        } finally {  
            if (out != null) {  
                out.close();  
            }  
        }  
    } 

}
